﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;

using Aliphant.Common;
using Aliphant.Common.Managers;
using Aliphant.Interfaces;
using Aliphant.IoC;

using Microsoft.Win32;

namespace Aliphant.UI.Services
{
    public class ThemeService
    {
        private const int WM_SETTINGCHANGE = 0x001A;
        private const string ThemeRegistryKey = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";

        // Win32 API 监听系统设置变化
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        private HwndSource? _hwndSource;

        public static ObservableCollection<ThemeInfo> Themes { get; } = new ObservableCollection<ThemeInfo>();

        public event Action? RefreshTheme;

        private IDictionary<int, ThemeInfo> _themes = new Dictionary<int, ThemeInfo>();

        public ThemeService()
        {
            LoadThemes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "themes"));
        }

        public void ListeningSysTheme()
        {
            _hwndSource = PresentationSource.FromVisual(Application.Current.MainWindow) as HwndSource;
            _hwndSource?.AddHook(WndProc);
            UpdateTheme();
        }

        /// <summary>
        /// 加载主题文件
        /// </summary>
        /// <param name="themeDirectory"></param>
        public void LoadThemes(string themeDirectory)
        {
            Themes.Clear();

            if (Directory.Exists(themeDirectory))
            {
                foreach (var file in Directory.GetFiles(themeDirectory, "*.xaml"))
                {
                    var theme = new ResourceDictionary { Source = new Uri(file) };
                    var info = new ThemeInfo
                    {
                        Id = (int)theme["Id"],
                        Name = (string)theme["Name"],
                        FilePath = file,
                        PreviewColor = (Color)theme["Color.Preview"]
                    };
                    Themes.Add(info);
                    _themes.Add(info.Id, info);
                }
            }
        }

        /// <summary>
        /// 应用主题文件
        /// </summary>
        /// <param name="themePath"></param>
        public void ApplyTheme(string themePath)
        {
            if (!File.Exists(themePath)) return;

            var newTheme = new ResourceDictionary { Source = new Uri(themePath, UriKind.Absolute) };

            Application.Current.Resources.MergedDictionaries.RemoveAt(1);
            Application.Current.Resources.MergedDictionaries.Insert(1, newTheme);
        }

        /// <summary>
        /// 应用主题文件
        /// </summary>
        /// <param name="id"></param>
        public void ApplyTheme(int id)
        {
            if (!_themes.ContainsKey(id))
            {
                // 不存在外观配置，就跟随系统
                UpdateTheme();
                return;
            }

            var path = _themes[id].FilePath;
            ApplyTheme(path);
        }

        /// <summary>
        /// 系统主题变化监听
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <param name="handled"></param>
        /// <returns></returns>
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_SETTINGCHANGE)
            {
                string? data = Marshal.PtrToStringAuto(lParam);
                if (data == "ImmersiveColorSet") // 主题变化信号
                {
                    UpdateTheme();
                }
            }
            return IntPtr.Zero;
        }

        /// <summary>
        /// 更新主题
        /// </summary>
        public void UpdateTheme()
        {
            if (ConfigManager.Instance.Settings.AppearanceType == Datas.AppearanceType.Light)
            {
                Application.Current.Dispatcher.BeginInvoke(() =>
                {
                    var theme = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "themes", "light.xaml");
                    ApplyTheme(theme);
                    // 页面刷新
                    RefreshTheme?.Invoke();
                });
                return;
            }
            if (ConfigManager.Instance.Settings.AppearanceType == Datas.AppearanceType.Dark)
            {
                Application.Current.Dispatcher.BeginInvoke(() =>
                {
                    var theme = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "themes", "dark.xaml");
                    ApplyTheme(theme);
                    // 页面刷新
                    RefreshTheme?.Invoke();
                });
                return;
            }

            Application.Current.Dispatcher.BeginInvoke((Action)(() =>
            {
                // 跟随系统切换主题
                var theme = IsSystemLightTheme()
                        ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "themes", "light.xaml")
                        : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "themes", "dark.xaml");

                ApplyTheme(theme);

                // 页面刷新
                RefreshTheme?.Invoke();
            }));
        }

        /// <summary>
        /// 判断系统主题是深色还是浅色
        /// </summary>
        /// <returns></returns>
        private static bool IsSystemLightTheme()
        {
            try
            {
                using (var key = Registry.CurrentUser.OpenSubKey(ThemeRegistryKey))
                {
                    return (int)(key?.GetValue("AppsUseLightTheme") ?? 1) == 1;
                }
            }
            catch
            {
                return true; // 默认浅色
            }
        }
    }

    public class ThemeInfo
    {
        public int Id { get; set; } = 0;

        public string Name { get; set; } = string.Empty;

        public string FilePath { get; set; } = string.Empty;

        public Color PreviewColor { get; set; } = Colors.Transparent;

    }
}
